package mws;

import lombok.Setter;
import mws.task.DelayedSwiftTask;
import mws.task.SwiftTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Stream;

@SuppressWarnings("uncheck")
public class SwiftBlockingQueue<T extends Runnable> implements SwiftBlockingQueueInterface<T> {

    private static final Logger log = LoggerFactory.getLogger(SwiftBlockingQueue.class);
    private final AtomicLong last_time = new AtomicLong(0);
    private final AtomicInteger index = new AtomicInteger(0);
    private final ReentrantLock mainLock = new ReentrantLock();
    private volatile int size;
    private BlockingQueue<T>[] blockingQueueArrays;
    private volatile int[] capacity = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE};
    @Setter
    private volatile long sleepTime = 100;
    private volatile long overTimeNa = TimeUnit.SECONDS.toMillis(100);

    // 构造函数1：使用无参供应者创建队列数组
    public SwiftBlockingQueue(BlockingQueueSupply<T, ? extends BlockingQueue<T>> supply) {
        blockingQueueArrays = new BlockingQueue[2];
        for (int i = 0; i < blockingQueueArrays.length; i++) {
            blockingQueueArrays[i] = supply.newBlockingQueue(); // 调用正确的创建方法
        }
    }

    // 构造函数2：使用带容量的供应者创建队列数组
    public SwiftBlockingQueue(BlockingQueueSupplyOnSize<T, ? extends BlockingQueue<T>> supply
            , int size) {
        blockingQueueArrays = new BlockingQueue[2];
        for (int i = 0; i < blockingQueueArrays.length; i++) {
            blockingQueueArrays[i] = supply.newBlockingQueue(size);
            capacity[i] = size;// 传入容量参数
        }
    }


    @Override
    public void WakeUpBlockingThreads(BlockingQueue lastBlockingQueue) {
        int record = 0;
        final long sleep_time = sleepTime;
        do {
            Runnable runnable = null;
            if(lastBlockingQueue instanceof DelayQueue<?>){
                runnable = new DelayedSwiftTask(null,true,80,TimeUnit.MILLISECONDS);
            }else {
                runnable = new SwiftTask(null, true);
            }
            lastBlockingQueue.offer(runnable);
            try {
                Thread.sleep(sleep_time);
            } catch (InterruptedException e) {
                System.out.println("休眠 100 毫秒");
            }
            record = lastBlockingQueue.size();
        } while (record == 0);
    }

    @Override
    public long getLastSwitchTime() {
        return last_time.get();
    }


    public BlockingQueue<T> getNowQueue() {
        mainLock.lock();
        try {
            return blockingQueueArrays[index.get()];
        } finally {
            mainLock.unlock();
        }

    }


    public List<BlockingQueue<T>> getQueue() {
        return Arrays.stream(blockingQueueArrays).toList();
    }

    //  有一个重大问题 假如 有些线程 正在take 然后此时 我切换了 但是take的那些并不知道 也就 意味着 有些线程会 永远阻塞在任务处 所以要么默认设置 这个timeout 要么 在切换之后唤醒
    public boolean swiftQueue(BlockingQueueSupplyOnSize<T, ? extends BlockingQueue<T>> supply, int size) {

//        if (last_time.get() == 0) {
//            if (last_time.compareAndSet(0, System.nanoTime())) {
//                int record = index.get();
//                if (capacity[record] == size) {
//                    // 如果大小相同 就只是清空
//                    BlockingQueue<T> array = blockingQueueArrays[record];
//                    ArrayList<T> list = new ArrayList<>();
//                    array.drainTo(list);
//                    if (!array.isEmpty()) {
//                        for (Object r : array.toArray(new Object[0])) {
//                            if (array.remove((T) r))
//                                list.add((T) r);
//                        }
//                    }
//                    //todo
//                    return true;
//                }
//                BlockingQueue<T> check = blockingQueueArrays[record == 0 ? 1 : 0];
//
//                if (check != null && check.isEmpty()) {
//                    log.error("也许会有问题 按道理不应该没有清理完成");
//                }
//
//                blockingQueueArrays[record == 0 ? 1 : 0] = supply.newBlockingQueue(size);
//                capacity[record == 0 ? 1 : 0] = size;
//                index.set(record == 0 ? 1 : 0);
//
//                BlockingQueue<T> drainList = blockingQueueArrays[record];
//                ArrayList<T> list = new ArrayList<>();
//                drainList.drainTo(list);
//                if (!drainList.isEmpty()) {
//                    for (Object r : drainList.toArray(new Object[0])) {
//                        if (drainList.remove((T) r))
//                            list.add((T) r);
//                    }
//                }
//                BlockingQueue<T> finalDrainList = drainList;
//                ThreadPoolContext.getInstance().getThreadPoolExecutor("commonThreadPool").
//                        submit(new SwiftTask(
//                                new Runnable() {
//                                    @Override
//                                    public void run() {
//                                        WakeUpBlockingThreads(finalDrainList);
//                                    }
//                                }
//                        ));
//
//                // todo
//                return true;
//            }
//        }
//
//
//        long nowTime = System.nanoTime();
//        if (nowTime - last_time.get() < overTimeNa) {
//            log.info("切换过于频繁 无法切换");
//            return false;
//        }
        //todo

        // todo 第一个线程改完了 然后第二个线程 又去改 这样不就 swift两次了吗
//        long temp = last_time.get();
//        if(last_time.compareAndSet(temp,getNowNano())){
//
//        }

        // 改成兜底 策略

        mainLock.lock();
        try {

            long nowTimeV2 = getNowMillis();

            if (nowTimeV2 - last_time.get() < overTimeNa) {
                log.info("切换过于频繁 无法切换");
                return false;
            }

            last_time.compareAndSet(last_time.get(), nowTimeV2);

            int record = index.get();
            if (capacity[record] == size) {
                BlockingQueue<T> drainList = blockingQueueArrays[record];
                ArrayList<T> list = new ArrayList<>();
                drainList.drainTo(list);
                if (!drainList.isEmpty()) {
                    for (Object r : drainList.toArray(new Object[0])) {
                        if (drainList.remove((T) r))
                            list.add((T) r);
                    }
                }
                //  相同size 就不用管了
                //todo
                return true;
            }
            BlockingQueue<T> check = blockingQueueArrays[record == 0 ? 1 : 0];

            if (check != null && check.size() > 0) {
                log.error("也许会有问题 按道理不应该没有清理完成");
            }

            blockingQueueArrays[record == 0 ? 1 : 0] = supply.newBlockingQueue(size);
            capacity[record == 0 ? 1 : 0] = size;
            index.set(record == 0 ? 1 : 0);

            BlockingQueue<T> drainList = blockingQueueArrays[record];
            ArrayList<T> list = new ArrayList<>();
            drainList.drainTo(list);
            if (!drainList.isEmpty()) {
                for (Object r : drainList.toArray(new Object[0])) {
                    if (drainList.remove((T) r))
                        list.add((T) r);
                }
            }
            BlockingQueue<T> finalDrainList = drainList;
            ThreadPoolContext.getInstance().getThreadPoolExecutor("commonThreadPool").
                    submit(new SwiftTask(
                            new Runnable() {
                                @Override
                                public void run() {
                                    WakeUpBlockingThreads(finalDrainList);
                                }
                            }
                    ));
            // todo
            return true;
        } finally {
            mainLock.unlock();
        }

    }

    ;


    public boolean quickSwiftQueue(BlockingQueueSupplyOnSize<T, ? extends BlockingQueue<T>> supply, int size) {
        BlockingQueue<T> drainList = null;

        mainLock.lock();
        try {

            int record = index.get();

            drainList = blockingQueueArrays[record];

            if (drainList != null && drainList.size() > 0) {
                log.error("也许会有问题 按道理不应该没有清理完成");
            }

            blockingQueueArrays[record == 0 ? 1 : 0] = supply.newBlockingQueue(size);

            capacity[record == 0 ? 1 : 0] = size;

            index.set(record == 0 ? 1 : 0);

        } finally {
            mainLock.unlock();
        }

        ArrayList<T> list = new ArrayList<>();
        drainList.drainTo(list);
        if (!drainList.isEmpty()) {
            for (Object r : drainList.toArray(new Object[0])) {
                if (drainList.remove((T) r))
                    list.add((T) r);
            }
        }
        BlockingQueue<T> finalDrainList = drainList;
        ThreadPoolContext.getInstance().getThreadPoolExecutor("commonThreadPool").
                submit(new SwiftTask(
                        new Runnable() {
                            @Override
                            public void run() {
                                WakeUpBlockingThreads(finalDrainList);
                            }
                        }
                ));

        // todo
        //

        return true;
    }

    ;


    private long getNowMillis() {
        return System.currentTimeMillis();
    }


    @Override
    public void forEach(Consumer action) {
        blockingQueueArrays[index.get()].forEach(action);
    }

    @Override
    public Object[] toArray(IntFunction generator) {
        return blockingQueueArrays[index.get()].toArray(generator);
    }

    @Override
    public boolean removeAll(Collection c) {
        return blockingQueueArrays[index.get()].removeAll(c);
    }

    @Override
    public int size() {
        return blockingQueueArrays[index.get()].size();
    }

    @Override
    public boolean isEmpty() {
        return blockingQueueArrays[index.get()].isEmpty();
    }

    @Override
    public Iterator<T> iterator() {
        return blockingQueueArrays[index.get()].iterator();
    }

    @Override
    public Object[] toArray() {
        return blockingQueueArrays[index.get()].toArray();
    }

    @Override
    public Object[] toArray(Object[] a) {
        throw new RuntimeException("toArray 暂未完成");
    }

    @Override
    public boolean addAll(Collection c) {
        return blockingQueueArrays[index.get()].addAll(c);
    }

    @Override
    public boolean removeIf(Predicate filter) {
        return blockingQueueArrays[index.get()].removeIf(filter);
    }

    @Override
    public boolean retainAll(Collection c) {
        throw new RuntimeException("retainAll 暂未完成");
    }


    @Override
    public void clear() {
        blockingQueueArrays[index.get()].clear();
    }

    @Override
    public Spliterator<T> spliterator() {
        return blockingQueueArrays[index.get()].spliterator();
    }

    @Override
    public Stream<T> stream() {
        return blockingQueueArrays[index.get()].stream();
    }

    @Override
    public Stream<T> parallelStream() {
        return blockingQueueArrays[index.get()].parallelStream();
    }

    @Override
    public T remove() {
        return blockingQueueArrays[index.get()].remove();
    }

    @Override
    public T poll() {
        return blockingQueueArrays[index.get()].poll();
    }

    @Override
    public T element() {
        return blockingQueueArrays[index.get()].element();
    }

    @Override
    public T peek() {
        return blockingQueueArrays[index.get()].peek();
    }

    @Override
    public boolean add(T o) {
        return blockingQueueArrays[index.get()].add((T) o);
    }

    @Override
    public boolean offer(T o) {
        return blockingQueueArrays[index.get()].offer((T) o);
    }

    @Override
    public void put(T o) throws InterruptedException {
        blockingQueueArrays[index.get()].put((T) o);
    }

    @Override
    public boolean offer(T o, long timeout, TimeUnit unit) throws InterruptedException {
        return blockingQueueArrays[index.get()].offer((T) o, timeout, unit);
    }

    @Override
    public T take() throws InterruptedException {

        return blockingQueueArrays[index.get()].take();
    }

    @Override
    public T poll(long timeout, TimeUnit unit) throws InterruptedException {
        return blockingQueueArrays[index.get()].poll(timeout, unit);
    }

    @Override
    public int remainingCapacity() {
        return blockingQueueArrays[index.get()].remainingCapacity();
    }

    @Override
    public boolean remove(Object o) {
        return blockingQueueArrays[index.get()].remove((T) o);
    }

    @Override
    public boolean containsAll(Collection c) {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return blockingQueueArrays[index.get()].contains((T) o);
    }


    @Override
    public int drainTo(Collection c) {
        throw new RuntimeException("drainTo 暂未完成");
    }

    @Override
    public int drainTo(Collection c, int maxElements) {
        throw new RuntimeException("drainTo 暂未完成");
    }

}
